﻿using DingTalk.Sdk.Reponse;
using DingTalk.Sdk.Request;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace DingTalk.Sdk
{
    public class DingTalkClient
    {
        private string _accessToken;
        private string _secret = string.Empty;
        private HttpClient _httpClient;
        private string _requestPath;

        public DingTalkClient(string webhook, string secret) : this(webhook)
        {
            _secret = secret;
        }

        public DingTalkClient(string webhook)
        {
            if( !Uri.TryCreate(webhook, UriKind.Absolute, out Uri uri))
            {
                throw new Exception("webhook地址不符，请填写正确的webhook地址");
            }
            var query =  HttpUtility.ParseQueryString(uri.Query);
            _accessToken = query["access_token"];
            _httpClient = new HttpClient();
            _httpClient.BaseAddress = new Uri($"{uri.Scheme}://{uri.Host}");
            _requestPath = uri.AbsolutePath;
        }

        public async Task<DingTalkResponse> SendTextAsync(string text, List<string> AtMobiles = null, List<string> atUserIds = null, bool isAtAll = false)
        {
            var request = new TextRequest()
            {
                At = new AtContent()
                {
                    AtMobiles = AtMobiles,
                    AtUserIds = atUserIds,
                    IsAtAll = isAtAll
                },
                Text = new TextContent()
                {
                    Content = text,
                }
            };
            return await SendAsync(request);
        }

        public async Task<DingTalkResponse> SendAsync(IRequest request)
        {
            var timestamp = GetTimestamp();
            var sign = !string.IsNullOrEmpty(_secret) ? GetSign(timestamp) : "";
            var requestUrl = $"{_requestPath}?access_token={_accessToken}&timestamp={timestamp}{(!string.IsNullOrEmpty(sign) ? $"&sign={sign}" : "")}";
            var content = new StringContent(JsonConvert.SerializeObject(request), Encoding.UTF8, "application/json");
            var rsp = await _httpClient.PostAsync(requestUrl, content);
            var responseStr = await rsp.Content.ReadAsStringAsync();
            return JsonConvert.DeserializeObject<DingTalkResponse>(responseStr);
        }

        private string GetSign(long timestamp)
        {
            string stringToSign = timestamp + "\n" + _secret;
            using (var hmacsha256 = new HMACSHA256(Encoding.UTF8.GetBytes(_secret)))
            {
                byte[] hashValue = hmacsha256.ComputeHash(Encoding.UTF8.GetBytes(stringToSign));
                var sign = HttpUtility.UrlEncode(Convert.ToBase64String(hashValue));
                return sign;
            }
        }

        private long GetTimestamp()
        {
            return (long)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalMilliseconds;
        }

        ~DingTalkClient()
        {
            try
            {
                _httpClient.Dispose();
            }
            catch { }
        }
    }
}
